#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle(tr("AutoTrans"));
    manager = new QNetworkAccessManager(this);
    connect(manager, &QNetworkAccessManager::finished, this, &MainWindow::recvReplyPost);
    initView();
    uiConnect();
}

void MainWindow::initView()
{
    ui->comboBox_src->addItem(tr("zh|中文简体"));
    ui->comboBox_src->addItem(tr("en|英文"));
    ui->comboBox_src->addItem(tr("spa|西班牙语"));
    ui->comboBox_src->addItem(tr("pt|葡萄牙语"));
    ui->comboBox_src->addItem(tr("jp|日语"));
    ui->comboBox_src->addItem(tr("kor|韩语"));
    ui->comboBox_src->addItem(tr("cht|中文繁体"));
    ui->comboBox_src->addItem(tr("de|德语"));
    ui->comboBox_src->addItem(tr("bur|缅甸语"));
    ui->comboBox_src->addItem(tr("th|泰语"));
    ui->comboBox_src->addItem(tr("fil|菲律宾语"));
    ui->comboBox_src->addItem(tr("fra|法语"));

    ui->comboBox_dst->addItem(tr("en|英文"));
    ui->comboBox_dst->addItem(tr("spa|西班牙语"));
    ui->comboBox_dst->addItem(tr("zh|中文简体"));
    ui->comboBox_dst->addItem(tr("pt|葡萄牙语"));
    ui->comboBox_dst->addItem(tr("jp|日语"));
    ui->comboBox_dst->addItem(tr("kor|韩语"));
    ui->comboBox_dst->addItem(tr("cht|中文繁体"));
    ui->comboBox_dst->addItem(tr("de|德语"));
    ui->comboBox_dst->addItem(tr("bur|缅甸语"));
    ui->comboBox_dst->addItem(tr("th|泰语"));
    ui->comboBox_dst->addItem(tr("fil|菲律宾语"));
    ui->comboBox_dst->addItem(tr("fra|法语"));

    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "源文本" << "翻译结果");

    ui->progressBar->setValue(0);
}

void MainWindow::uiConnect()
{
    connect(ui->pushButton_start, &QPushButton::clicked, this, &MainWindow::sendPostRequest);
    connect(ui->pushButton_save, &QPushButton::clicked, this, &MainWindow::saveTranslationResults);
    connect(ui->pushButton_openFile, &QPushButton::clicked, this, [=](){
        QString filePath = QFileDialog::getOpenFileName(this, tr("打开文件"), tr("."), tr("ts文件(*.ts)"));
        if(!filePath.isEmpty())
        {
            ui->lineEdit_filePath->setText(filePath);
            //读取xml文件的节点
            // 1. 打开XML文件
            QFile file(filePath);
            if (!file.open(QIODevice::ReadOnly)) {
                qWarning() << "无法打开XML文件";
                return;
            }

            // 2. 创建DOM文档并解析
            QString errorMsg;
            int errorLine, errorColumn;
            if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn)) {
                qWarning() << "XML解析错误:"
                           << errorMsg << "at line" << errorLine << ", column" << errorColumn;
                file.close();
                return;
            }
            file.close();

            // 3. 获取根元素
            QDomElement root = doc.documentElement();
            qDebug() << "根元素名称:" << root.tagName();

            //4.获取节点名称为message的节点
            nodeList = doc.elementsByTagName("message");
            qDebug() << "message节点数量: " << nodeList.count();

            //将待翻译文本写入表格
            for(int i = 0; i < nodeList.count(); ++i)
            {
                QDomElement elementSource = nodeList.at(i).firstChildElement("source");
                QDomElement elementTranslation = nodeList.at(i).firstChildElement("translation");
                if(!elementSource.isNull() && !elementTranslation.isNull())
                {
                    ui->tableWidget->insertRow(ui->tableWidget->rowCount());  //插入行
                    QTableWidgetItem *itemSource = new QTableWidgetItem(elementSource.text());
                    itemSource->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置文本居中对齐
                    itemSource->setFlags(itemSource->flags() & (~Qt::ItemIsEditable));// 设置单元格不可编辑
                    ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, itemSource);
                    QTableWidgetItem *itemTranslation = new QTableWidgetItem(elementTranslation.text());
                    itemTranslation->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置文本居中对齐
                    ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, itemTranslation);
                }
                else
                {
                    ui->tableWidget->insertRow(ui->tableWidget->rowCount());  //插入行
                    QTableWidgetItem *itemSource = new QTableWidgetItem("xml解析错误");
                    itemSource->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置文本居中对齐
                    itemSource->setFlags(itemSource->flags() & (~Qt::ItemIsEditable));// 设置单元格不可编辑
                    ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, itemSource);
                    QTableWidgetItem *itemTranslation = new QTableWidgetItem("xml解析错误");
                    itemTranslation->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置文本居中对齐
                    ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, itemTranslation);
                }
            }
        }
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::sendPostRequest()
{
    if(ui->tableWidget->rowCount() == 0)
    {
        QMessageBox::information(this, "tips", "请先加载文件!", QMessageBox::Ok);
        return;
    }
    if(ui->comboBox_src->currentText() == ui->comboBox_dst->currentText())
    {
        QMessageBox::information(this, "tips", "目标语言和源语言不能相同!", QMessageBox::Ok);
        return;
    }
    recvNum = 0;
    setUIEnable(false);
    QString from = ui->comboBox_src->currentText().split("|")[0];  //原文本的类型
    QString to = ui->comboBox_dst->currentText().split("|")[0];    //译文的类型
    QString appid = ui->lineEdit_appID->text();  //翻译软件上申请的应用ID
    QString appkey = ui->lineEdit_key->text();  //APPID对应的秘钥
    QString strUrl = "https://fanyi-api.baidu.com/api/trans/vip/translate";
    QUrl url(strUrl);


    //组合翻译文本、生成签名
    int startIndex = 0;  //每个请求的开始索引
    int num = 0;  //每个请求已添加的数据个数
    int endIndex = 0;
    while(startIndex + num < ui->tableWidget->rowCount())
    {
        qApp->processEvents();
        QString q = "";  //待翻译文本(query)
        QString salt = QString::number(QRandomGenerator::global()->bounded(0, 999999999)); // 生成一个0到999999999之间的随机数

        while(num < requestWordNum && endIndex < ui->tableWidget->rowCount())
        {
            if(ui->tableWidget->item(endIndex, 0)->text() != "xml解析错误")
            {
                q += ui->tableWidget->item(endIndex, 0)->text();
                ++num;
                if(num != requestWordNum && endIndex != ui->tableWidget->rowCount() - 1)
                {
                    q += "\n";
                }
            }
            ++endIndex;
        }
        QString strSign = appid + q + salt + appkey;  //签名的str形式
        QString sign = QCryptographicHash::hash(strSign.toUtf8(), QCryptographicHash::Md5).toHex(); //使用MD5加密

        //发送请求
        QNetworkRequest request(url);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

        //构建请求参数（自动编码）
        QUrlQuery query;
        query.addQueryItem("q", q);  // 自动编码中文
        query.addQueryItem("from", from);
        query.addQueryItem("to", to);
        query.addQueryItem("appid", appid);
        query.addQueryItem("salt", salt);
        query.addQueryItem("sign", sign);
        QByteArray postData = query.query().toUtf8();  // 获取编码后的参数字符串并转为UTF-8

        QNetworkReply *reply = manager->post(request, postData);
        replyMap.insert(reply, startIndex);
        startIndex = endIndex;
        num = 0;
        sleep_test(100);
    }
}

void MainWindow::recvReplyPost(QNetworkReply* reply)
{
    QByteArray all = reply->readAll();
    //qDebug() << all;
    QJsonDocument doc = QJsonDocument::fromJson(all);
    QJsonObject obj = doc.object();  //获取根对象
    if (!obj.contains("error_code"))
    {
        QJsonArray trans_result = obj["trans_result"].toArray();
        int start = replyMap.find(reply).value();
        for(int i = 0; i < trans_result.count(); ++i)
        {
            QJsonObject res = trans_result[i].toObject();
            QString src = res["src"].toString();
            QString dst = res["dst"].toString();
            //qDebug() << "源文本: " << src << "翻译文本: " << dst;
            ui->tableWidget->item(start + i, 1)->setText(dst);
        }
        recvNum += trans_result.count();
        double percent = ((double)recvNum) / ui->tableWidget->rowCount();
        ui->progressBar->setValue((int)(percent * 100));
        qApp->processEvents();
        if(recvNum == ui->tableWidget->rowCount())
        {
            setUIEnable(true);
        }
    }
    else
    {
        QString error_code = obj["error_code"].toString();
        QString error_msg = obj["error_msg"].toString();
        qCritical() << "错误代码:" << error_code << ", 错误消息:" << error_msg;
    }

    // 释放资源（避免内存泄漏）
    reply->deleteLater();
}

void MainWindow::sleep_test(unsigned int msec){
    //currnentTime 返回当前时间 用当前时间加上我们要延时的时间msec得到一个新的时刻
    QTime reachTime = QTime::currentTime().addMSecs(msec);
    //用while循环不断比对当前时间与我们设定的时间
    while (QTime::currentTime() < reachTime)
    {
        //如果当前的系统时间尚未达到我们设定的时刻，就让Qt的应用程序类处理消息队列中的事件，
        //以使程序仍处于响应状态。一旦到达了我们设定的时刻，就跳出该循环，继续执行后面的语句。
        //QApplication::processEvents(QEventLoop::AllEvents, 1);
        QCoreApplication::processEvents();
    }
}

void MainWindow::setUIEnable(bool enable)
{
    ui->pushButton_start->setEnabled(enable);
    ui->pushButton_openFile->setEnabled(enable);
    ui->comboBox_dst->setEnabled(enable);
    ui->comboBox_src->setEnabled(enable);
    ui->lineEdit_appID->setEnabled(enable);
    ui->lineEdit_key->setEnabled(enable);
    ui->pushButton_save->setEnabled(enable);
}

void MainWindow::saveTranslationResults()
{
    if(ui->tableWidget->rowCount() == 0)
    {
        QMessageBox::information(this, "tips", "请先加载文件!", QMessageBox::Ok);
        return;
    }
    setUIEnable(false);
    for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
    {
        QDomElement e = nodeList.at(i).firstChildElement("translation");
        //修改节点文本内容
        QDomText newText = doc.createTextNode(ui->tableWidget->item(i, 1)->text());
        if(e.childNodes().size() == 0)  //如果没有文本节点，就新增一个
        {
            e.appendChild(newText);
        }
        else  //如果有文本节点，就修改文本节点的值
        {
            e.firstChild().setNodeValue(newText.nodeValue());
        }
        if(e.hasAttribute("type"))  //移除type属性
        {
            e.removeAttribute("type");
        }
        double percent = ((double)i) / (ui->tableWidget->rowCount() - 1);
        ui->progressBar->setValue((int)(percent * 100));
        qApp->processEvents();
    }
    //保存修改后的XML
    QFile outFile(ui->lineEdit_filePath->text());
    if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        qWarning() << "无法打开输出文件";
        return;
    }

    QTextStream stream(&outFile);
    stream.setEncoding(QStringConverter::Utf8); // 设置编码
    doc.save(stream, 4); // 4是缩进空格数
    outFile.close();
    setUIEnable(true);
    QMessageBox::information(this, "tips", "文件保存成功!", QMessageBox::Ok);
}
